package com.springboot.fram.core.charsets;

import org.apache.commons.lang3.StringUtils;

import java.io.UnsupportedEncodingException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 字符编码工具类
 *
 * @author _minus
 * @create 2017-11-06 18:38
 */
public class CharsetUtils {
	private enum Charset {
		/** 7位ASCII字符，也叫作ISO646-US、Unicode字符集的基本拉丁块 */
		US_ASCII("US-ASCII", "位ASCII字符，也叫作ISO646-US、Unicode字符集的基本拉丁块 "),
		ISO_8859_1("ISO-8859-1", "ISO 拉丁字母表 No.1，也叫作 ISO-LATIN-1"),
		UTF_8("UTF-8", "8 位 UCS 转换格式"),
		UTF_16BE("UTF-16BE", "16 位 UCS 转换格式，Big Endian（最低地址存放高位字节）字节顺序"),
		UTF_16LE("UTF_16LE", "16 位 UCS 转换格式，Big Endian（最低地址存放高位字节）字节顺序"),
		UTF_16("UTF_16", "16 位 UCS 转换格式，字节顺序由可选的字节顺序标记来标识"),
		GBK("GBK", "中文超大字符集");

		private String encode;
		private String desc;

		public String getEncode() {
			return encode;
		}

		public void setEncode(String encode) {
			this.encode = encode;
		}

		public String getDesc() {
			return desc;
		}

		public void setDesc(String desc) {
			this.desc = desc;
		}

		private Charset(String encode, String desc) {
			this.encode = encode;
			this.desc = desc;

		}

	}

	/**
	 * 获取传入字符串的编码格式
	 *
	 * @param str
	 * @return
	 */
	public static String getEncode(String str) throws UnsupportedEncodingException {
		if (!StringUtils.isEmpty(str)) {
			for (Charset charset : Charset.values()) {
				if (str.equals(new String(str.getBytes(charset.getEncode()), charset.getEncode()))) {
					return charset.getEncode();
				}
			}
		}
		throw new UnsupportedEncodingException("编码库中不存在");
	}

	public static String stringToUnicode(String s) {
		StringBuffer out = new StringBuffer();
		// 直接获取字符串的unicode二进制
		byte[] bytes = null;
		try {
			bytes = s.getBytes("unicode");
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// 然后将其byte转换成对应的16进制表示即可
		for (int i = 0; i < bytes.length - 1; i += 2) {
			out.append("\\u");
			String str = Integer.toHexString(bytes[i + 1] & 0xff);
			for (int j = str.length(); j < 2; j++) {
				out.append("0");
			}
			String str1 = Integer.toHexString(bytes[i] & 0xff);
			out.append(str1);
			out.append(str);
		}
		return out.toString();

	}

	/**
	 * 字符串转换unicode
	 *
	 * @param string
	 * @return
	 */
	public static String string2Unicode(String string) {
		StringBuffer unicode = new StringBuffer();
		for (int i = 0; i < string.length(); i++) {
			// 取出每一个字符
			char c = string.charAt(i);
			// 转换为unicode
			unicode.append("\\u" + Integer.toHexString(c));
		}

		return unicode.toString();
	}

	/**
	 * 解码 Unicode2 \\uXXXX
	 *
	 * @param str
	 * @return
	 */
	public static String unicodeToString(String str) {
		String s2 = null;
		try {
			byte[] converttoBytes = str.getBytes("UTF-8");
			s2 = new String(converttoBytes, "UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return s2;
	}

	/**
	 * 含有unicode 的字符串转一般字符串
	 *
	 * @param unicodeStr 混有 Unicode 的字符串
	 * @return
	 */
	public static String unicodeStr2String(String unicodeStr) {
		int length = unicodeStr.length();
		int count = 0;
		//正则匹配条件，可匹配“\\u”1到4位，一般是4位可直接使用 String regex = "\\\\u[a-f0-9A-F]{4}";
		String regex = "\\\\u[a-f0-9A-F]{1,4}";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(unicodeStr);
		StringBuffer sb = new StringBuffer();

		while (matcher.find()) {
			String oldChar = matcher.group();//原本的Unicode字符
			String newChar = unicode2String(oldChar);//转换为普通字符
			// int index = unicodeStr.indexOf(oldChar);
			// 在遇见重复出现的unicode代码的时候会造成从源字符串获取非unicode编码字符的时候截取索引越界等
			int index = matcher.start();

			sb.append(unicodeStr.substring(count, index));//添加前面不是unicode的字符
			sb.append(newChar);//添加转换后的字符
			count = index + oldChar.length();//统计下标移动的位置
		}
		sb.append(unicodeStr.substring(count, length));//添加末尾不是Unicode的字符
		return sb.toString();
	}

	/**
	 * unicode 转字符串
	 *
	 * @param unicode 全为 Unicode 的字符串
	 * @return
	 */
	public static String unicode2String(String unicode) {
		StringBuffer string = new StringBuffer();
		String[] hex = unicode.split("\\\\u");

		for (int i = 1; i < hex.length; i++) {
			// 转换出每一个代码点
			int data = Integer.parseInt(hex[i], 16);
			// 追加成string
			string.append((char) data);
		}

		return string.toString();
	}

	/**
	 * @param value
	 * @return 字符串转Ascii码
	 */
	public static String stringToAscii(String value) {
		StringBuffer sbu = new StringBuffer();
		char[] chars = value.toCharArray();
		for (int i = 0; i < chars.length; i++) {
			if (i != chars.length - 1) {
				sbu.append((int) chars[i]).append(",");
			} else {
				sbu.append((int) chars[i]);
			}
		}
		return sbu.toString();
	}

	/**
	 * @param value
	 * @return ascii码转字符串
	 */
	public static String asciiToString(String value) {
		StringBuffer sbu = new StringBuffer();
		String[] chars = value.split(",");
		for (int i = 0; i < chars.length; i++) {
			sbu.append((char) Integer.parseInt(chars[i]));
		}
		return sbu.toString();
	}

	/**
	 * 字符串编码转换的实现方法
	 *
	 * @param str
	 *            待转换编码的字符串
	 * @param newCharset
	 *            目标编码
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String changeCharset(String str, String newCharset) throws UnsupportedEncodingException {
		if (str != null) {
			// 获取到原字符编码
			String charsetName = getEncode(str);
			System.out.println("原字符编码为：" + charsetName);
			// 用默认字符编码解码字符串。
			byte[] bs = str.getBytes(charsetName);
			// 用新的字符编码生成字符串
			return new String(bs, newCharset);
		}
		return null;
	}

	/**
	 * 将字符编码转换成US-ASCII码
	 */
	public static String toASCII(String str) throws UnsupportedEncodingException {
		return changeCharset(str, Charset.US_ASCII.getEncode());
	}

	/**
	 * 将字符编码转换成ISO-8859-1码
	 */
	public static String toISO_8859_1(String str) throws UnsupportedEncodingException {
		return changeCharset(str, Charset.ISO_8859_1.getEncode());
	}

	/**
	 * 将字符编码转换成UTF-8码
	 */
	public static String toUTF_8(String str) throws UnsupportedEncodingException {
		return changeCharset(str, Charset.UTF_8.getEncode());
	}

	/**
	 * 将字符编码转换成UTF-16BE码
	 */
	public static String toUTF_16BE(String str) throws UnsupportedEncodingException {
		return changeCharset(str, Charset.UTF_16BE.getEncode());
	}

	/**
	 * 将字符编码转换成UTF-16LE码
	 */
	public static String toUTF_16LE(String str) throws UnsupportedEncodingException {
		return changeCharset(str, Charset.UTF_16LE.getEncode());
	}

	/**
	 * 将字符编码转换成UTF-16码
	 */
	public static String toUTF_16(String str) throws UnsupportedEncodingException {
		return changeCharset(str, Charset.UTF_16.getEncode());
	}

	/**
	 * 将字符编码转换成GBK码
	 */
	public static String toGBK(String str) throws UnsupportedEncodingException {
		return changeCharset(str, Charset.GBK.getEncode());
	}

}
